home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
GCC
/
V2-4-5
/
GCCEXTSR
/
Virtual
/
!Virtual
/
c
/
control
next >
Wrap
Text File
|
1993-09-07
|
36KB
|
1,386 lines
/*
* control.c
* Part of the !Virtual distribution
* (c) bdb/nas/fo, 1992-3
*/
/* includes */
#include "swis.h"
#include "swiv.h"
#include "wimp.h"
#include "virtual.h"
#include "lib.h"
#include "pager.h"
#include "output.h"
#include "asm.h"
#include "poll.h"
#include "xswis.h" /* Some RO3 swis */
/* constants */
/*#define DEBUG*/
#define N_bit 0x80000000
#define Z_bit 0x40000000
#define C_bit 0x20000000
#define V_bit 0x10000000
#define PSW_bits 0xF0000000
static int * const swivec=(int*)8;
static int wimp_version;
/* errors */
#define ERR(x) ((struct Error *)(x))
static char BadMemory[] = { "XXXXNo memory at this address" };
static char Failed[] = { "XXXXMisc Virtual swi failed" };
static char NotAllowed[] = { "XXXXThis swi not allowed under virtual" };
/* module wrapping */
struct Error *Cinit(private **p) /* */
{ /* called with C stack a 1K bit out of svcstack. */
struct Error *err;
if (!*p)
*p=alloc(sizeof(private));
(*p)->uses = 0;
(*p)->w = 0;
worksemaphore = 1;
err = swix(OS_CallEvery,IN(R0|R1|R2),15,&OurCallEvery,*p);
if (err)
free(*p),*p=0;
return err;
}
struct Error *Cfinish(private **p)
{ /* called with C stack a 1K bit out of svcstack. */
/* should check (*p)->uses */
return swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,*p);
}
struct Error *CDoPhysical(int task, int addr, int len, int k[3],private *priv)
{ /* called with C stack a 1K bit out of svcstack. */
WKSP *w=priv->w;
RANGE r;
if (w->ourtask!=task)
return 0;
r = Locate(w,addr,addr+len);
k[0]=r.start; k[1]=r.end; k[2]=w->pagefile;
return 0;
}
/* ******************** mode changers */
void ClaimVVecs(WKSP *w)
{ int oldswi;
workptr=w;
swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),2,&VPrefetchAbort,&w->OldPrefetchAbort);
swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),3,&VDataAbort,&w->OldDataAbort);
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),7,&VCallBack,w,&w->regs,
&w->OldCallBack,&w->OldCallBackR12,&w->OldCallBackRegs);
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&VError,&w->errnum,&w->errPC);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&VUpCall,w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&VExit,w);
oldswi=*swivec;
if (oldswi>>24==0xEA)
; /* B */
oldswi=8+(int)swivec+(oldswi<<8>>6);
w->OldSWIV=oldswi;
workOldSWIV=oldswi;
*swivec=(int)&VSWIV-8-(int)swivec>>2|0xEA000000;
}
void ReleaseVVecs(WKSP *w)
{
*swivec=w->OldSWIV-8-(int)swivec>>2|0xEA000000;
swi(OS_ChangeEnvironment,IN(R0|R1),2,w->OldPrefetchAbort);
swi(OS_ChangeEnvironment,IN(R0|R1),3,w->OldDataAbort);
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),7,w->OldCallBack,w->OldCallBackR12,w->OldCallBackRegs);
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
}
void ClaimExtVecs( WKSP *w )
{ swi(OS_Claim,IN(R0|R1|R2),3,&ExtWriteC,w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&ExtError,w,&w->errPC);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&ExtUpCall,w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&ExtExit,w);
}
void ReleaseExtVecs( WKSP *w )
{ swi(OS_Release,IN(R0|R1|R2),3,&ExtWriteC,w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
}
void Virtual(WKSP *w)
{
virtualmem(w);
ClaimVVecs(w);
}
void Normal(WKSP *w)
{
ReleaseVVecs(w);
normalmem(w);
}
void V2Ext( WKSP *w )
{
ReleaseVVecs(w);
ClaimExtVecs(w);
}
void Ext2V( WKSP *w )
{
ReleaseExtVecs(w);
ClaimVVecs(w);
}
void Ext2Norm( WKSP *w)
{
ReleaseExtVecs(w);
normalmem(w);
}
void Norm2Ext( WKSP *w)
{
virtualmem(w);
ClaimExtVecs(w);
}
/* ******************** Virtual mode handlers */
WKSP *CVWantAddr(WKSP *w, int start, int len)
{
if (len<0)
start += len, len= -len;
if (w->regs[15]&3)
{ Normal(w);
printf("***** CWantAddr called from non-user mode. Disaster! *****\n");
RealDoOff(w);
}
if (!WriteRange(w,start,start+len))
{ Normal(w);
printf("***** CWantAddr can't get desired area: %08x+%08x****\n",start,len);
RealDoOff(w);
}
return w;
}
void doeschand(WKSP *w,int n)
{ w->EscapeCondition = n;
if (w->Escape != -1) {
int result, * ruser = w->regs;
if (w->EscapeR12 != -1)
WriteRange(w, w->EscapeR12, w->EscapeR12+512);
ReadRange(w, w->Escape, w->Escape+8);
result = CallEscapeHandler(w->Escape, w->EscapeR12, (w->EscapeCondition == 2) ? 0x40 : 0);
if (result == 1) {
int j, * rcallback = (int *) w->CallBackBuf;
/* call back flag is set */
WriteRange(w, w->CallBackR12, w->CallBackR12 + 512);
WriteRange(w, w->CallBackBuf, w->CallBackBuf + 16 * 4);
ReadRange(w, w->CallBack, w->CallBack + 8);
for (j = 0; j < 16; j++)
rcallback[j] = ruser[j]; /* save user registers into callback buffer */
ruser[12] = w->CallBackR12;
ruser[15] = w->CallBack;
}
}
}
WKSP *CVCallBack(WKSP *w)
{ Normal(w);
Poll(w);
Virtual(w);
if (1==w->EscapeCondition)
doeschand(w,2);
worksemaphore=1; /* Ready to reenable when we exit */
return w;
}
WKSP *CVSWIV(WKSP *w,int instr)
{
int *r=w->regs;
char s[256];
struct Error *err=0;
int psw,i;
int swinum=instr&~(XOS_Bit|0xFF000000);
r[15]&=~V_bit;
#if 0
Normal(w);
swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
printf("Swi %s PC=%08x ",s,r[15]);
for (i=0;i<=14;i++)
printf("R%d=%08x ",i,r[i]);
printf("...");
Virtual(w);
#endif
switch(swinum) {
/* input/output */
/*
* OS SWIs
*/
case OS_WriteC:
outc(w,r[0]);
break;
case OS_Write0:
{ char *p;
ReadRange(w,r[0],r[0]+1);
for (p=(char *)r[0];*p;p++)
{ ReadPtr(w,(int)p);
outc(w,*p);
}
r[0]=(int)++p;
}
break;
case OS_WriteS:
{ char *p=(char *)(r[15]&~0xfc000003);
char *q=p;
for (;*p;p++)
{ ReadPtr(w,(int)p);
outc(w,*p);
}
r[15]+=(((p+1)-q)|3)+1;
}
break;
case OS_WriteN:
{ int n;
for ( n=0; n<r[1]; n++ )
{ ReadPtr(w,r[0]+n);
outc(w,((char *)r[0])[n]);
}
}
break;
case OS_NewLine:
outc(w,'\r'); outc(w,'\n');
break;
case OS_ReadC:
r[0]=getc(w);
if (-1==r[0])
{ r[0] = 27;
r[15]|=C_bit;
}
else
r[15]&=~C_bit;
if (1==w->EscapeCondition)
doeschand(w,2);
break;
case OS_ReadLine:
{ char buf[256];
int n=0,c;
r[15]&=~C_bit;
for (;;)
{ c=getc(w);
switch (c)
{
case 13: case 10:
buf[n]=13;
break;
case 27: case -1:
r[15]|=C_bit;
break;
case 127: case 8:
if (n>0)
{ outc(w,127); n--; }
else
outc(w,7);
continue;
case 21:
while (n>0)
{ outc(w,127); n--; }
continue;
default:
if (r[2]<=c && c<=r[3])
{ if (n<r[1]-1 && n<255)
{ buf[n++]=c;
outc(w,c);
}
else
outc(w,7);
}
else
outc(w,7);
continue;
}
outc(w,'\r'); outc(w,'\n');
break;
}
WriteRange(w,r[0],r[0]+n+1);
memcpy((void *)r[0],buf,n+1);
r[1]=n;
}
if (1==w->EscapeCondition)
doeschand(w,2);
break;
case OS_Byte:
switch (r[0])
{ default: goto uk;
case 0: /* display os version */
Normal(w);
err = swix(OS_Byte,IN(R0|R1)|OUT(R1),0,r[1],&r[1]);
Virtual(w);
break;
case 2: /* switch input streams */
#ifdef DEBUG
Normal(w);
printf("(FX 2,%d)",r[1]);
Virtual(w);
#endif
break;
case 3: /* switch output streams */
#ifdef DEBUG
Normal(w);
printf("(FX 3,%d)",r[1]);
Virtual(w);
#endif
break;
case 15: /* clear input or all buffers */
break;
case 21: /* clear specific buffer */
break;
case 124: /* clear esc cond immed */
w->EscapeCondition = 0;
break;
case 125: /* cause esc cond */
doeschand(w,2);
break;
case 126: /* acknowledge escape cond */
r[1]=w->EscapeCondition?0xff:0;
if (w->EscapeCondition)
doeschand(w,0);
break;
case 129: /* read keyboard for information */
if (r[2] != 0xFF)
{
r[1]=lowgetc(w);
if (r[1] == -1) r[2] = 0xFF;
else r[2] = 0;
} else goto uk;
break;
case 160:
case 161:
err = swix(OS_Byte,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
break;
case 0xDA: /* Read/write bytes in VDU queue */
r[1]=0;
break;
case 0xDC: /* Read/write escape character */
{ int old = w->EscapeChar;
w->EscapeChar = (w->EscapeChar&r[2])^r[1];
r[1] = old;
break;
}
case 0xE5: /* Read/write escape char enable */
{ int old = w->EscapeCharEnable;
w->EscapeCharEnable = (w->EscapeCharEnable&r[2])^r[1];
r[1] = old;
break;
}
}
break;
case OS_Plot:
Normal(w);
err = swix(OS_Plot,IN(R0|R1|R2),r[0],r[1],r[2]);
Virtual(w);
break;
case OS_SerialOp:
err = ERR(&NotAllowed);
break;
case OS_Word:
switch (r[0])
{ default: goto uk;
case 1: case 2: case 3: case 4: case 14:
WriteRange(w, r[1],r[1]+256);
err = swix(OS_Word,IN(R0|R1),r[0],r[1]);
break;
}
break;
case OS_ReadUnsigned:
ReadRange(w,r[1],r[1]+256);
err = swix(OS_ReadUnsigned,IN(R0|R1|R2)|OUT(R1|R2),r[0],r[1],r[2],&r[1],&r[2]);
break;
case OS_EnterOS:
#ifdef DEBUG
Normal(w);
printf("***OS_EnterOS (ignored) from %08x ****\n",r[15]);
Virtual(w);
#endif
if (w->ingos) {
r[15] = r[15] | 0x03;
}
break;
case OS_IntOff:
#ifdef DEBUG
Normal(w);
printf("***OS_IntOff (ignored) from %08x ****\n",r[15]);
Virtual(w);
#endif
break;
case OS_IntOn:
#ifdef DEBUG
Normal(w);
printf("***OS_IntOn (ignored) from %08x ****\n",r[15]);
Virtual(w);
#endif
break;
case OS_Exit:
#ifdef DEBUG
Normal(w);
printf("***OS_Exit from %08x ****\n",r[15]);
Virtual(w);
#endif
if (-1==w->Exit)
{
if (w->started_ingos) {
usermode();
strcpy(w->command, "gos");
swi(OS_CLI,IN(R0),w->command);
}
else {
Normal(w);
printflush(w);
RealDoOff(w);
}
}
/*
* The return value Sys$ReturnCode has to be set here
* Normally OS_Exit does this, but is never called here.
*/
if (r[1] == 0x58454241) { /* ABEX */
int val = r[2];
Normal(w);
err = swix(OS_SetVarVal, IN(R0|R1|R2|R3|R4),"Sys$ReturnCode", &val, 4, 0, 1);
Virtual(w);
}
r[15] = w->Exit;
r[12] = w->ExitR12;
break;
case OS_GenerateError:
{ char buf[264];
Normal(w);
FromMem(w,r[0],buf,sizeof(buf));
printf("***GenerateError: PC=%08x %d %s\n",r[15],((int *)buf)[0],buf+4);
Virtual(w);
}
getc(w);
err = (void *)r[0];
break;
case OS_ChangeEnvironment:
switch (r[0])
{ int t;
#define ifswap(x,y) ((x)?((t)=(x),(x)=(y),(y)=(t)):((x)=(y)))
default: goto uk;
case 0: ifswap(r[1],w->MemoryLimit); break;
case 1: ifswap(r[1],w->UndefinedInstruction); break;
case 2: ifswap(r[1],w->PrefetchAbort); break;
case 3: ifswap(r[1],w->DataAbort); break;
case 4: ifswap(r[1],w->AddressException); break;
case 5: ifswap(r[1],w->OtherExceptions); break;
case 6: ifswap(r[1],w->Error); ifswap(r[2],w->ErrorR0); ifswap(r[3],w->ErrorBuf); break;
case 7: ifswap(r[1],w->CallBack); ifswap(r[2],w->CallBackR12); ifswap(r[3],w->CallBackBuf); break;
case 8: ifswap(r[1],w->BreakPoint); ifswap(r[2],w->BreakPointR12); ifswap(r[3],w->BreakPointBuf); break;
case 9: ifswap(r[1],w->Escape); ifswap(r[2],w->EscapeR12); break;
case 10: ifswap(r[1],w->Event); ifswap(r[2],w->EventR12); break;
case 11: ifswap(r[1],w->Exit); ifswap(r[2],w->ExitR12); break;
case 12: ifswap(r[1],w->UnusedSWI); ifswap(r[2],w->UnusedSWIR12); break;
case 13: ifswap(r[1],w->ExceptionRegs); break;
case 14: ifswap(r[1],w->ApplicationSpace); break;
case 15: ifswap(r[1],w->CurrentlyActiveObject); break;
case 16: ifswap(r[1],w->UpCall); ifswap(r[2],w->UpCallR12); break;
}
break;
case OS_SetEnv:
{ int t;
ifswap(r[0],w->Exit);
ifswap(r[1],w->MemoryLimit);
ifswap(r[2],w->ApplicationSpace);
ifswap(r[4],w->UndefinedInstruction);
ifswap(r[5],w->PrefetchAbort);
ifswap(r[6],w->DataAbort);
ifswap(r[7],w->AddressException);
}
break;
case OS_Control: {
int t;
ifswap(r[0],w->Error); ifswap(r[1],w->ErrorBuf);
ifswap(r[2],w->Escape);
ifswap(r[3],w->Event);
}
break;
case OS_ReadVduVariables: {
int i = 0, value;
Normal(w);
while (FromMem(w, r[0] + i, &value, 4), value != -1) i += 4;
Virtual(w);
ReadRange(w, r[0], r[0] + i);
WriteRange(w, r[1], r[1] + i);
err = swix(OS_ReadVduVariables, IN(R0|R1), r[0], r[1]);
}
break;
case OS_GetEnv:
r[0]=(int)&w->command[0];
r[1]=w->MemoryLimit;
r[2]=(int)&w->starttime[0];
break;
case OS_ReadVarVal:
ReadRange(w,r[0],r[0]+256);
if (r[2]>=0)
WriteRange(w,r[1],r[1]+r[2]);
err = swix(OS_ReadVarVal,IN(R0|R1|R2|R3|R4)|OUT(R2|R3|R4),r[0],r[1],r[2],r[3],r[4],&r[2],&r[3],&r[4]);
break;
case OS_SetVarVal:
ReadRange(w, r[0], r[0] + 256);
if (r[2] > 0)
ReadRange(w, r[1], r[1] + r[2]);
if (r[3] > 0)
ReadRange(w, r[3], r[3] + 256);
err = swix(OS_SetVarVal,IN(R0|R1|R2|R3|R4)|OUT(R3|R4),r[0],r[1],r[2],r[3],r[4],&r[3],&r[4]);
break;
case OS_Module:
switch (r[0])
{ default: goto uk;
case 6:
Normal(w);
err = swix(OS_Module,IN(R0|R3)|OUT(R2),r[0],r[3],&r[2]);
Virtual(w);
break;
case 7:
Normal(w);
err = swix(OS_Module,IN(R0|R2),r[0],r[2]);
Virtual(w);
break;
case 18:
ReadRange(w,r[1],r[1]+256);
err = swix(OS_Module,IN(R0|R1)|OUT(R1|R2|R3|R4|R5),
r[0],r[1],&r[1],&r[2],&r[3],&r[4],&r[5]);
break;
}
break;
case OS_ConvertHex8:
WriteRange(w,r[1],r[1]+r[2]);
err = swix(OS_ConvertHex8,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
break;
case OS_CLI:
{ char buf[256];
Normal(w);
FromMem(w,r[0],buf,sizeof(buf));
if ((buf[0]|0x20)=='g' && (buf[1]|0x20)=='o' && (buf[2]|0x20)=='s' && buf[3]<=' ')
w->ingos = 1;
/*
* Before loading a new programme into memory the old and new pages
* should be on the same addresses.
*/
FixMemoryPages(w);
{
int i = 0;
while ((w->command[i] = buf[i]) >= ' ') i++;
w->command[i] = 0;
}
err=swix(OS_CLI,IN(R0),buf);
Virtual(w);
}
break;
case OS_Mouse:
Normal(w);
err = swix(OS_Mouse,OUT(R0|R1|R2|R3),&r[0],&r[1],&r[2],&r[3]);
Virtual(w);
break;
case OS_ReadMonotonicTime:
Normal(w);
err = swix(OS_ReadMonotonicTime,OUT(R0),&r[0]);
Virtual(w);
break;
case OS_SWINumberFromString:
{ char buf[256];
Normal(w);
FromMem(w,r[1],buf,sizeof(buf));
err=swix(OS_SWINumberFromString,IN(R1)|OUT(R0),&buf,&r[0]);
Virtual(w);
}
break;
/* Filesystem SWIs */
case OS_Find:
if (!r[0])
{ Normal(w);
err = swix(OS_Find,IN(R0|R1)|OUT(PSW),r[0],r[1],&psw);
Virtual(w);
}
else
{ char name[256];
char path[256];
Normal(w);
FromMem(w,r[1],name,sizeof(name));
if ((r[0]&3)==1 || (r[0]&3)==2)
FromMem(w,r[2],path,sizeof(path));
err = swix(OS_Find,IN(R0|R1|R2)|OUT(PSW|R0),r[0],name,path,&psw,&r[0]);
Virtual(w);
}
break;
case OS_BGet: case OS_BPut: case OS_Args:
Normal(w);
err=swix(swinum,IN(R0|R1|R2)|OUT(PSW|R0|R1|R2),r[0],r[1],r[2],&psw,&r[0],&r[1],&r[2]);
r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
Virtual(w);
break;
case OS_GBPB:
Normal(w);
if (1<=r[0] && r[0]<=4)
{ /* read/write variety */
while (r[3]>0)
{ RANGE k = Physical(w,r[2],r[2]+r[3]);
int p = k.start;
int l = k.end-k.start;
int q,m;
err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),r[0],r[1],p,l,r[4],&psw,&q,&m,&r[4]);
r[2]+=q-p;
r[3]-=l-m;
if (err || m)
break;
} }
else if (5<=r[0] && r[0]<=8)
{ char buf[2048];
FromMem(w,r[2],buf,sizeof(buf));
err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R3|R4),r[0],buf,r[2],r[3],r[4],&psw,&r[3],&r[4]);
ToMem(w,buf,r[2],sizeof(buf));
}
else if (9<=r[0] && r[0]<=12)
{ char dirname[256];
char wild[256];
RANGE k;
FromMem(w,r[1],&dirname,sizeof(dirname));
if (r[6])
FromMem(w,r[6],&wild,sizeof(wild));
k = Physical(w,r[2],r[2]+r[5]);
err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(PSW|R3|R4),
r[0],dirname,k.start,r[3],r[4],k.end-k.start,r[6]?wild:0,
&psw,&r[3],&r[4]);
}
else
{ Virtual(w);
goto uk;
}
r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
Virtual(w);
break;
case OS_File:
Normal(w);
switch(r[0])
{ default: Virtual(w); goto uk;
case 0: case 10: /* save a block of memory */
{
char name[256];
int s[16];
int h;
FromMem(w,r[1],name,sizeof(name));
err = swix(OS_Find,IN(R0|R1)|OUT(R0),0x8F,name,&h);
if (err) break;
/* write code from OS_GBPB handler above */
s[0]=2; s[1]=h; s[2]=r[4]; s[3]=r[5]-r[4];
while (s[3]>0)
{ RANGE k = Physical(w,s[2],s[2]+s[3]);
int p = k.start;
int l = k.end-k.start;
int q,m;
err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),s[0],s[1],p,l,s[4],&psw,&q,&m,&s[4]);
s[2]+=q-p;
s[3]-=l-m;
if (err || m)
break;
}
err = swix(OS_Find,IN(R0|R1),0,h);
if (err) break;
if (r[0] == 0)
{
err = swix(OS_File,IN(R0|R1|R2),2,name,r[2]);
if (err) break;
err = swix(OS_File,IN(R0|R1|R3),3,name,r[3]);
} else
{
err = swix(OS_File,IN(R0|R1|R2),18,name,r[2]);
}
break;
}
case 5: case 13: case 15: case 17: /* read cat info */
case 20: case 21: case 22: case 23:
{ int h;
char path[256];
char name[256];
FromMem(w,r[1],name,sizeof(name));
if (r[0]==13 || r[0]==15 || r[0]==21 || r[0]==22)
FromMem(w,r[4],path,sizeof(path));
err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5|R6),r[0],name,path,
&r[0],&r[2],&r[3],&r[4],&r[5],&h);
if (20<=r[0] && r[0]<=23)
r[6]=h;
break;
}
case 1: case 2: case 3: case 4: case 9: case 18: /* Write cat info */
case 6: /* Delete */
case 7: case 11: /* Create */
case 8: /* Create directory */
{ char name[256];
FromMem(w,r[1],name,sizeof(name));
err = swix(OS_File,IN(R0|R1|R2|R3|R4|R5)|OUT(R0|R2|R3|R4|R5),r[0],name,r[2],r[3],r[4],r[5],
&r[0],&r[2],&r[3],&r[4],&r[5]);
break;
}
case 12: case 14: case 16: case 255: /* load */
{ int h;
char path[256];
char name[256];
RANGE k;
int l,m,q;
int p=(r[3]&0xFF)?-1:r[2];
int t = r[0]==255?0:r[0]==12?1:r[0]==14?2:r[0]==16?3:0;
FromMem(w,r[1],name,sizeof(name));
if (t==1 || t==2)
FromMem(w,r[4],path,sizeof(path));
err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5),"\x05\x0D\x0F\x11"[t],name,path,
&r[0],&r[2],&r[3],&r[4],&r[5]);
if (err)
break;
err = swix(OS_Find,IN(R0|R1|R2)|OUT(R0),0x4C+t,name,path,&h);
if (err)
break;
if (p==-1)
p = r[2];
l = r[4];
while (l>0)
{ k = Physical(w,p,p+l);
if (!k.start)
{ err=ERR(&BadMemory);
break;
}
err = swix(OS_GBPB,IN(R0|R1|R2|R3)|OUT(R2|R3),4,h,k.start,k.end-k.start,&q,&m);
if (err)
break;
if (q!=k.end || m)
{ err = ERR(&Failed);
break;
}
p+=k.end-k.start;
l-=k.end-k.start;
}
if (!err)
err = swix(OS_Find,IN(R0|R1),0,h);
else
(void)swix(OS_Find,IN(R0|R1),0,h);
}
}
Virtual(w);
break;
case OS_FSControl:
Normal(w);
switch (r[0])
{ default: Virtual(w); goto uk;
case 27: /* Wipe objects */
{ char name[256];
FromMem(w,r[1],name,sizeof(name));
err = swix(OS_FSControl,IN(R0|R1|R2|R3|R4|R5|R6|R7),r[0],name,r[2],r[3],r[4],r[5],r[6],r[7]);
break;
}
}
Virtual(w);
break;
/*
* RISCOS extension module SWIs
*/
#ifndef SharedCLibrary_LibInitAPCS_R
#define SharedCLibrary_LibInitAPCS_R 0x80681
#endif
case SharedCLibrary_LibInitAPCS_R:
ReadRange(w,r[0],r[0]+256);
WriteRange(w,r[1],r[1]+32768);
err = swix(SharedCLibrary_LibInitAPCS_R,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(R0|R1|R2|R6),
r[0],r[1],r[2],r[3],r[4],r[5],r[6],&r[0],&r[1],&r[2],&r[6]);
break;
case DDEUtils_Prefix:
Normal(w);
if (r[0] > 0) ReadRange(w,r[0],r[0]+256);
err = swix(DDEUtils_Prefix, IN(R0), r[0]);
Virtual(w);
break;
case DDEUtils_SetCLSize:
Normal(w);
free(w->DDECL);
w->DDECLSize = r[0];
w->DDECL = alloc(r[0]);
Virtual(w);
break;
case DDEUtils_SetCL:
Normal(w);
FromMem(w,r[0],w->DDECL,w->DDECLSize);
Virtual(w);
break;
case DDEUtils_GetCLSize:
r[0] = w->DDECLSize;
break;
case DDEUtils_GetCL:
Normal(w);
ToMem(w,w->DDECL,r[0],w->DDECLSize);
w->DDECLSize = 0;
Virtual(w);
break;
case DDEUtils_ThrowbackStart:
Normal(w);
err = swix(DDEUtils_ThrowbackStart,0);
Virtual(w);
break;
case DDEUtils_ThrowbackSend:
{ char file[256];
char msg[256];
Normal(w);
FromMem(w,r[2],&file,sizeof(file));
if (r[0])
FromMem(w,r[5],&msg,sizeof(msg));
err = swix(DDEUtils_ThrowbackSend,IN(R0|R2|R3|R4|R5),r[0],file,r[3],r[4],msg);
Virtual(w);
break;
}
case DDEUtils_ThrowbackEnd:
Normal(w);
err = swix(DDEUtils_ThrowbackEnd,0);
Virtual(w);
break;
case MessageTrans_Lookup:
case MessageTrans_ErrorLookup:
ReadRange(w,r[1],r[1]+256);
if (r[2])
WriteRange(w,r[2],r[2]+r[3]);
err = swix(swinum,IN(R0|R1|R2|R3|R4|R5|R6|R7)|OUT(R0|R2|R3),
r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],&r[0],&r[2],&r[3]);
break;
case Wimp_ReadSysInfo:
err = swix(Wimp_ReadSysInfo,IN(R0)|OUT(R0),r[0],&r[0]);
break;
case Wimp_SendMessage:
ReadRange(w,r[1],r[1]+256);
err = swix(Wimp_SendMessage,IN(R0|R1|R2)|OUT(R2),r[0],r[1],r[2],&r[2]);
break;
case FPEmulator_Version:
err = swix(FPEmulator_Version,OUT(R0),&r[0]);
break;
case Territory_ReadCurrentTimeZone:
err = swix(Territory_ReadCurrentTimeZone,OUT(R0|R1),&r[0],&r[1]);
break;
case Territory_ReadTimeZones:
err = swix(Territory_ReadTimeZones,IN(R0)|OUT(R0|R1|R2|R3),r[0],&r[0],&r[1],&r[2],&r[3]);
break;
case Territory_ConvertTimeToOrdinals:
ReadRange(w,r[1],r[1]+5);
WriteRange(w,r[2],r[2]+32);
err = swix(Territory_ConvertTimeToOrdinals,IN(R0|R1|R2),r[0],r[1],r[2]);
break;
case Wimp_SlotSize:
/*
* When this SWI is allowed, the wimpslot will be expanded to the
* maximum value, or sometimes to a wrong value.
* In the first case there is no space left for Edit's taskwindow,
* so Virtual will stop.
* I think a programme running under Virtual must not change its
* 'Wimp_Slot'. The user can make any changes to the WimpSlot by
* dragging a bar in the Tasks window.
*
* When a task wants to enlarge the wimpslot, ie make the 'DiskSlot'
* bigger, will this be allowed.
*
* So this code is not compiled
*
swi(Wimp_SlotSize,IN(R0|R1),OUT(R1|R2),-1,r[1],&r[1],&r[2]);
if (r[0]!=-1)
{ w->ApplicationSpace = r[0];
w->MemoryLimit = r[0];
}
r[0]=w->ApplicationSpace;
break;
*
* So here's my new code
*/
if (r[0] != -1) {
if (r[0] > w->ApplicationSpace - K32) { /* task asks for wimpslot extension */
int i, OldAppSpace = w->ApplicationSpace;
w->ApplicationSpace = ADDR(PLACE(r[0] + K32 + K32));
if (w->ApplicationSpace > M24)
w->ApplicationSpace = M24;
w->MemoryLimit = w->ApplicationSpace;
for (i = PLACE(OldAppSpace); i < PLACE(w->ApplicationSpace); i++) {
w->ourmem[i] = TAGLOC(ZERO, 0);
}
}
}
r[0] = w->ApplicationSpace - K32;
break;
/* BASICTrans swis */
case BASICTrans_HELP:
case BASICTrans_Message:
case BASICTrans_Error:
V2Ext(w);
err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
OUT(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
&r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
Ext2V(w);
break;
case TaskWindow_TaskInfo:
Normal(w);
if (r[0] == 0)
r[0] = 1;
else
err = swix(TaskWindow_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
Virtual(w);
break;
case Virtual_TaskInfo:
Normal(w);
if (r[0] == 0)
r[0] = 1;
else
err = swix(Virtual_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
Virtual(w);
break;
case VM_TaskInfo:
err = ERR(&NotAllowed);
break;
/*
* Default (unrecognized SWIs) handling
*/
default:
if (swinum>=0x100 && swinum<0x200)
{ outc(w,(char)swinum);
break;
}
uk:
Normal(w);
swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
printf("UKSwi %s PC=%08x ",s,r[15]);
for (i=0;i<=8;i++)
printf("R%d=%08x ",i,r[i]);
printf("Allow(Yn)?\n");
Virtual(w);
lp:
switch (getc(w))
{ case -1:
w->EscapeCondition = 0;
/* FALL THROUGH */
default:
goto lp;
case 'n': case'N':
err = ERR(&NotAllowed);
break;
case 'y': case 'Y': case 13:
V2Ext(w);
err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
OUT(PSW|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
&psw,&r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
Ext2V(w);
break;
}
break;
}
if (!err)
return w;
if (instr&XOS_Bit) /* X form */
{ r[0]=(int)err;
r[15]|=V_bit;
return w;
}
if (-1==w->Error)
{ Normal(w);
printf("***Error:%s",err->msg);
RealDoOff(w);
}
WriteRange(w,w->ErrorBuf,w->ErrorBuf+264);
((int*)w->ErrorBuf)[0] = r[15];
((int*)w->ErrorBuf)[1] = err->num;
strcpy( (char *)&((int*)w->ErrorBuf)[2], err->msg );
r[0] = w->ErrorR0;
r[15] = w->Error & ~3;
return w;
}
int CVUpCall( int r0, int r1, int r2, WKSP *w)
{ /* Called with sp a 1K chunk out of svcstack */
switch(r0)
{ case 256:
r0 = 0; /* Not quite sure what on earth is going on here, but better stop it! */
break;
default:
break;
}
return r0;
}
/* ******************** Ext mode handlers */
int CExtWriteC(int c, WKSP *w)
{ /* called with stack a 1K bit out of svcstack */
w->outbuf[w->outcount++]=c;
if (w->outcount>=OUTMAX-2)
{ Ext2Norm(w);
printflush(w);
FindPages(w);
Norm2Ext(w);
}
return 0x80000000; /* VC CC */
}
int CExtUpCall(int r0,int r1,int r2,WKSP *w)
{ /* Called with sp a 1K chunk out of svcstack */
switch(r0)
{ case 256:
r0 = 0;
break;
default:
break;
}
return r0;
}
int CExtError(WKSP *w)
{ /* Called in user, ext mode */
printf("ExtError PC=%08x errnum %d errmess %s****\n",w->errPC,w->errnum,w->errmess);
Ext2V(w);
return (int)&w->errnum;
}
void CExtExit(WKSP *w)
{ /* Called in user, ext mode */
Ext2V(w);
}
/* ******************** Normal mode handlers */
void __main(private *p,char *cmd)
{ /* This is called in user mode, with its stack at the top of the WimpSlot */
wimp_eventdata b;
struct Error *e;
char *buf[512];
int ourtask,outtask,txt,i;
WKSP *w;
#ifdef DEBUG
printf("%s\n", cmd);
#endif
swi(OS_ReadArgs,IN(R0|R1|R2|R3),
",wimpslot/K,name/K,pagefile/K,ctrl/S,display/S,quit/S,task,txt,discslot/K,nice/K", cmd, buf, sizeof(buf));
#ifdef DEBUG
printf("os_readargs passed\n");
#endif
if (buf[0] == 0) {
strcpy(b.msg.data.chars+8, "gos ");
strcpy(b.msg.data.chars+12, cmd);
}
else
strcpy(b.msg.data.chars+8,cmd);
swi(Wimp_Initialise,IN(R0|R1|R2)|OUT(R0|R1),200,0x4b534154,
buf[2]?buf[2]:"Virtual",&wimp_version,&ourtask);
if (!buf[7] || !buf[8])
{ memcpy(b.msg.data.chars,"virtual ",8);
b.msg.hdr.action = 0x808c5; /* TaskWindow_NewTask; */
b.msg.hdr.your_ref = 0;
b.msg.hdr.size = (21+(strlen(b.msg.data.chars)|3));
swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,0);
swi(OS_Exit,0);
}
outtask = xtoi(buf[7]);
txt = xtoi(buf[8]);
b.msg.hdr.action = /*TaskWindow_Ego*/ 0x808c2;
b.msg.hdr.your_ref = 0;
b.msg.data.words[0]=txt;
b.msg.hdr.size = 24;
swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,outtask);
w = alloc(sizeof(WKSP));
p->w = w;
p->uses++;
w->private = p;
w->outtask = outtask;
w->ourtask = ourtask;
w->outcount = 0;
w->incount = 0;
w->instart = 0;
w->EscapeCondition = 0;
w->EscapeChar = 27;
w->EscapeCharEnable = 0;
w->ingos = 0;
w->started_ingos = 0;
w->moreavailable = 0;
/* check for DDE extended command line */
e = swix(DDEUtils_GetCLSize, OUT(R0), &i);
if ((!e) && (i != 0))
{
w->DDECL = alloc(i);
w->DDECLSize = i;
swix(DDEUtils_GetCL, IN(R0), w->DDECL);
} else
{
w->DDECL = 0;
w->DDECLSize = 0;
}
if (buf[10] == 0)
{
w->nice_run = 15; /* default */
w->nice_delay = 0;
} else
{
int level =sizetoi(buf[10]);
w->nice_delay = 0;
switch (level)
{
case 0: w->nice_run = 100;break;
case 1: w->nice_run = 75; break;
case 2: w->nice_run = 45; break;
case 3: w->nice_run = 25; break;
case 4: w->nice_run = 15; break;
case 5: w->nice_run = 13;
w->nice_delay = 10;
break;
case 6: w->nice_run = 11;
w->nice_delay = 25;
break;
case 7: w->nice_run = 8;
w->nice_delay = 50;
break;
case 8: w->nice_run = 7;
w->nice_delay = 80;
break;
case 9: w->nice_run = 5;
w->nice_delay = 100;
break;
default: w->nice_run = 100; break;
}
}
e = swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,p);
e = swix(OS_CallEvery,IN(R0|R1|R2),w->nice_run,&OurCallEvery,p);
strcpy(w->pagefilename,buf[3]?buf[3]:"<Swap$Path>pagefile0");
strcpy(w->command,buf[0]?buf[0]:"GOS");
w->ApplicationSpace=buf[9]?sizetoi(buf[9])+K32:M24;
if (w->ApplicationSpace>M24)
w->ApplicationSpace=M24;
if (buf[1] != 0)
{
int slotsize = sizetoi(buf[1]);
if (slotsize<K32) slotsize = K32;
swi(Wimp_SlotSize, IN(R0|R1), slotsize, -1);
}
w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
i=0;
while (0!=(e=swix(OS_Find,IN(R0|R1)|OUT(R0),0x80,w->pagefilename,&w->pagefile)) && i<10)
w->pagefilename[strlen(w->pagefilename)-1]++,i++;
if (e)
{ swi(Wimp_ReportError,IN(R0|R1|R2),e,2,"Virtual");
swi(OS_Exit,0);
}
svcmode();
swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
#ifdef DEBUG
printf("cmd=%s\n",w->command);
printf("wimpslot=%08x\n",w->ApplicationSpace);
printf("name=%s\n",buf[2]);
printf("pagefile=%s\n",w->pagefilename);
printf("ctrl=%08x\n",(int)buf[4]);
printf("display=%08x\n",(int)buf[5]);
printf("quit=%08x\n",(int)buf[6]);
printf("task=%08x\n",outtask);
printf("txt=%08x\n",txt);
printf("nice=%d\n",w->nice_run);
#endif
swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),6,&NormError,w,&w->errPC,
&w->OldError,&w->OldErrorR0,&w->OldErrorBuf);
swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),16,&NormUpCall,w,&w->OldUpCall,&w->OldUpCallR12);
swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),11,&NormExit,w,&w->OldExit,&w->OldExitR12);
Initourmem(w);
SetWimpMemMap(w);
SetVirtualSlot(w,w->ApplicationSpace-K32);
w->MemoryLimit = w->ApplicationSpace;
#ifdef DEBUG
printf("Going virtual\n");
#endif
Virtual(w);
usermode();
worksemaphore = 0; /* Enable interupts */
#ifdef DEBUG
swi(OS_Write0,IN(R0),"This is virtual: OS_CLI ");
swi(OS_Write0,IN(R0),w->command);
swi(OS_NewLine,0);
#endif
if ((w->command[0]|0x20)=='g' && (w->command[1]|0x20)=='o' && (w->command[2]|0x20)=='s' && w->command[3]<=' ')
w->started_ingos = 1;
else
w->started_ingos = 0;
if (buf[6] == 0) w->started_ingos = 1;
swi(OS_CLI,IN(R0),w->command);
swi(OS_Exit,0);
}
void RealDoOff(WKSP *w)
{
private *priv=w->private;
wimp_eventdata b;
#ifdef DEBUG
printf("RealDoOff\n");
#endif
swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
printflush(w);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),6,w->OldError,w->OldErrorR0,w->OldErrorBuf);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,w->OldExit,w->OldExitR12);
swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,w->OldUpCall,w->OldUpCallR12);
Finishourmem(w);
usermode();
b.msg.hdr.action = /*TaskWindow_Morio*/ 0x808c3;
b.msg.hdr.your_ref = 0;
b.msg.hdr.size = 20;
swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,w->outtask);
swi(Wimp_CloseDown, 0);
swix(OS_Find,IN(R0|R1),0,w->pagefile);
swix(OS_File,IN(R0|R1),6,w->pagefilename);
free((char *)w->stacktop-STACKSIZE);
free(w->DDECL);
free(w);
priv->uses--;
priv->w = 0;
swi(OS_Exit,0);
}
int CNormError( WKSP *w )
{ printf("NormError: PC=%08x errnum %d errmess %s\n",w->errPC,w->errnum,w->errmess);
swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
swi(Wimp_ReportError,IN(R0|R1|R2),&w->errnum,2,"Virtual");
swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
RealDoOff(w);
return 0;
}
void CNormExit(WKSP *w)
{
#ifdef DEBUG
printf("NormExit\n");
#endif
RealDoOff(w);
}
int CNormWriteC(int c, WKSP *w)
{ /* called with stack a 1K bit out of svcstack */
w->outbuf[w->outcount++]=c;
if (w->outcount>=OUTMAX-2)
{ printflush(w);
FindPages(w);
}
return 0x80000000; /* VC CC */
}
int CNormUpCall(int r0,int r1,int r2,WKSP *w)
{ /* Called with sp a 1K chunk out of svcstack */
switch(r0)
{ case 256:
{ char *cmd, *tptr;
Virtual(w);
swi(OS_GetEnv,OUT(R0|R2),&cmd,&tptr);
if ((w->command[0]|0x20)=='g' && (w->command[1]|0x20)=='o' && (w->command[2]|0x20)=='s' && w->command[3]<=' ')
w->ingos = 1;
else
w->ingos = 0;
/*
* Only execute this under RO3
*/
if (wimp_version >= 300) strcpy(w->command,cmd);
memcpy(w->starttime,tptr,5);
worksemaphore = 0; /* Enable interrupts */
break;
}
default:
break;
}
return r0;
}